<html>
    <head>
        <title>Minimal GLSL viewer</title>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
        
        <!-- WebGL GLES2 template -->
        
        <script type = "glsl" id = "standard-vs">precision mediump float;
            attribute vec4 a_Position;
            void main() {
            gl_Position = a_Position;
            }
        </script>
        <script type = "glsl" id = "standard-frag">precision mediump float;
            uniform float u_time;
            uniform vec2 u_resolution;
            void main( void ) {
            vec4 f=vec4(0.);
            vec2 u = gl_FragCoord.xy / u_resolution.xy; 
            float x,c;
            for (float i = 1.; i < 20.; i++)   
            f = u.y+.04*i < sin(c=floor(x= 2e2*u.x/i + 9.*i + u_time)) ? 
            f + min(15.*((x-=c)-x*x),1.) *(i/20.-f)  : f; 
            gl_FragColor = f;
            }
        </script>
        
        
        <!-- WebGL2 GLES3 template -->
        <!--
        <script type = "glsl" id = "standard-vs">#version 300 es
            precision highp float;
            in vec4 a_Position;
            void main() {
            gl_Position = a_Position;
            }
        </script>
        <script type = "glsl" id = "standard-frag">#version 300 es
            precision highp float;
            uniform float u_time;
            uniform vec2 u_resolution;
            out vec4 out_color;
            void main( void ) {
            vec4 f=vec4(0.);
            vec2 u = gl_FragCoord.xy / u_resolution.xy; 
            float x,c;
            for (float i = 1.; i < 20.; i++)   
            f = u.y+.04*i < sin(c=floor(x= 2e2*u.x/i + 9.*i + u_time)) ? 
            f + min(15.*((x-=c)-x*x),1.) *(i/20.-f)  : f; 
            out_color = f;
            }
        </script>
        -->
        
    </head>
    <body style = "background: #202020; padding: 32px;">
        <canvas id = "gl" width = "800" height = "600"></canvas>
        <script type = "text/javascript">
            "use strict";
            var width = 800;
            var height = 600;
            
            var gl = null;
            var Shader = null;
            var time_start = null;
            
            function InitializeShader(gl, source_vs, source_frag, fv, ff)
            {
                var ErrorMessage = "Initializing Shader Program: <" + fv + ">, <" + ff + ">";
                var shader_vs = gl.createShader(gl.VERTEX_SHADER);
                var shader_frag = gl.createShader(gl.FRAGMENT_SHADER);
                gl.shaderSource(shader_vs, source_vs);
                gl.shaderSource(shader_frag, source_frag);
                gl.compileShader(shader_vs);
                gl.compileShader(shader_frag);
                var error = false;
                if (!gl.getShaderParameter(shader_vs, gl.COMPILE_STATUS)) {
                    ErrorMessage += gl.getShaderInfoLog(shader_vs);
                    error = true;
                }
                if (!gl.getShaderParameter(shader_frag, gl.COMPILE_STATUS)) {
                    ErrorMessage += gl.getShaderInfoLog(shader_frag);
                    error = true;
                }
                var program = gl.createProgram();
                var ret = gl.getProgramInfoLog(program);
                if (ret != "")
                    ErrorMessage += ret;
                gl.attachShader(program, shader_vs);
                gl.attachShader(program, shader_frag);
                if (gl.linkProgram(program) == 0) {
                    ErrorMessage += "\r\ngl.linkProgram(program) failed with error code 0.";
                    error = true;
                }
                gl.validateProgram(program);
                if ( !gl.getProgramParameter( program, gl.LINK_STATUS) ) {
                  var info = gl.getProgramInfoLog(program);
                  ErrorMessage += "Could not compile WebGL program."+'\n\n' + info+'\n\n';
                  ErrorMessage += gl.getExtension('WEBGL_debug_shaders').getTranslatedShaderSource(shader_frag)+'\n\n';
                  error = true;
                }
                if (error) {
                    console.log(ErrorMessage + ' ...failed to initialize shader.');
                    return false;
                } else {
                    console.log(ErrorMessage + ' ...shader successfully created.');
                    return program;
                }
            }
            
            function animation_frame(T){
                if (!time_start)
                    time_start = T;
                if (!gl) {
                    console.log("ERROR: webgl lost");
                    return;
                }
                var iTime = (T - time_start) / 1000;
                gl.clearColor(0.0, 0.0, 0.0, 1.0);
                gl.clear(gl.COLOR_BUFFER_BIT);
                gl.useProgram(Shader);
                gl.uniform1f(gl.getUniformLocation(Shader, "u_time"), iTime);
                gl.uniform2f(gl.getUniformLocation(Shader, "u_resolution"), width, height);
                gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0);
                window.requestAnimationFrame(animation_frame);
            }
            
            document.addEventListener("DOMContentLoaded", function (event) {
                var canvas = document.getElementById('gl');
                gl = canvas.getContext("webgl2");
                if (!gl) {
                    console.log('webgl2 not supported, trying webgl');
                    gl = canvas.getContext("webgl")|| canvas.getContext("experimental-webgl") || canvas.getContext("moz-webgl") || canvas.getContext("webkit-3d");
                    if (!gl) {
                        console.log('webgl not suported');
                        return;
                    } else {
                        console.log('continue using webgl');
                    }
                } else {
                    console.log('continue with webgl2');
                }
                    var vs = document.getElementById("standard-vs").innerHTML;
                    var fs = document.getElementById("standard-frag").innerHTML;
                    Shader = InitializeShader(gl, vs, fs);
                    var vertices = new Float32Array([
                        -1.001, 3.001, 0.0,
                        -1.001, -1.001, 0.0,
                        3.001, -1.001, 0.0,
                    ]);
                    var indices = [0, 1, 2];
                    var vertexbuffer = gl.createBuffer();
                    var indexbuffer = gl.createBuffer();
                    gl.bindBuffer(gl.ARRAY_BUFFER, vertexbuffer);
                    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
                    gl.bindBuffer(gl.ARRAY_BUFFER, null);
                    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexbuffer);
                    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
                    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
                    gl.bindBuffer(gl.ARRAY_BUFFER, vertexbuffer);
                    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexbuffer);
                    gl.viewport(0, 0, width, height);
                    var coords = gl.getAttribLocation(Shader, "a_Position");
                    gl.vertexAttribPointer(coords, 3, gl.FLOAT, false, 0, 0);
                    gl.enableVertexAttribArray(coords);
                    window.requestAnimationFrame(animation_frame);
            });
        </script>
    </body>
</html>
